#include "sys_audio.h"
#include "app_data/log.h"
#include <string>
#include <variant>
#include <vector>

#define AUDIO_WARNING "36.警示语.mp3"
#define AUDIO_OPERATION_SUCCESS "37.操作成功.mp3"
#define AUDIO_VIP_TO_FRONT_DESK "39.的贵宾来一下前台.mp3"
#define AUDIO_POINT "40.点.mp3"
#define AUDIO_ROOM_HOUR_CALL "42.房间点钟.mp3"
#define AUDIO_ROOM_CLEAN_START "43.房间开始清扫.mp3"
#define AUDIO_ROOM_LINE_CALL "44.房间排钟.mp3"
#define AUDIO_ROOM_CLEAN_END "45.房间清扫结束，您辛苦了.mp3"
#define AUDIO_ROOM_HOUR_EXIST "46.房间有点钟.mp3"
#define AUDIO_RESERVATION_AVAILABLE "48.分有预约.mp3"
#define AUDIO_MINUTE "49.分钟.mp3"
#define AUDIO_MINUTE_TO_HOUR "50.分钟到钟.mp3"
#define AUDIO_SERVICE_END "51.服务结束，您辛苦了.mp3"
#define AUDIO_SERVICE_CANCELLED "52服务已取消.mp3"
#define AUDIO_REMAINING "56.还有.mp3"
#define AUDIO_HAO "57.号.mp3"
#define AUDIO_VIP_SERVICE "58.号贵宾服务.mp3"
#define AUDIO_MSG_ARRIVED "60.来信息了，请刷卡查看.mp3"
#define AUDIO_FRONT_DESK_CALL "61.请来一下前台.mp3"
#define AUDIO_GLAD_TO_SERVE "62.很高兴为.mp3"
#define AUDIO_GLAD_TO_SERVE_YOU "63.很高兴为您服务.mp3"
#define AUDIO_BACK_CLOCK_SUCCESS "66.回钟已经成功.mp3"
#define AUDIO_ADD_CLOCK_SUCCESS "67.加钟成功继续为您服务.mp3"
#define AUDIO_CAR_PLATE "71.请车牌尾号是.mp3"
#define AUDIO_PLEASE_TO "72.请您到.mp3"
#define AUDIO_CARD_SWIPE_SUCCESS "74.刷卡成功.mp3"
#define AUDIO_LEAVE_ROOM "75.催房.mp3"
#define AUDIO_EXPIRED_WRISTBAND "77.无效手牌，请检查.mp3"
#define AUDIO_CONSUMPTION "79.消费.mp3"
#define AUDIO_TIME_UP "81.已经到钟.mp3"
#define AUDIO_LOCATION "83.在.mp3"
#define AUDIO_CALLING_SERVICE "84.正在呼叫服务，请稍等.mp3"
#define AUDIO_REMIND_AFTER_ALL_HOURS "86.全部下钟后提醒.mp3"

#define AUDIO_REMINDER_SOUND "90-嘀嘀嘀.wav"
#define AUDIO_CARD_SWIPE_SOUND "91-刷卡声.wav"
#define AUDIO_TIMEOUT "97.已超时.mp3"
#define AUDIO_CLICK "95-点击声.wav"

#define AUDIO_TEN "十.mp3"
#define AUDIO_HUNDRED "百.mp3"
#define AUDIO_THOUSAND "千.mp3"
#define AUDIO_TEN_THOUSAND "万.mp3"

#define TAG "SysAudio"

enum class AudioType {
    STR_TEXT,       // std::string 文本播报
    STR_CN_TEXT,    // std::string 中文数字播报
    INT_TEXT,       // int 数字播报
    INT_CN_TEXT,    // int 中文数字播报
    DIRECT          // 直接播放
};

struct node {
    AudioType type;
    std::variant<std::string, int> data;
};

namespace {
    constexpr const char* EXT = ".mp3";

    inline std::string makePath(char c) {
        if (std::isupper(static_cast<unsigned char>(c))) c = static_cast<char>(std::tolower(c));

        return DeviceState::getInstance().audioFilePath + std::string(1, c) + EXT;
    }

    inline std::string makePath(const std::string& name) {
        return DeviceState::getInstance().audioFilePath + name + EXT;
    }

    struct AudioFunc {
        // 文本播报，例如车牌A12345，则需要播报A12345
        // 中文数字播报，例如1235则播报1千2百3十5
        void GenerateFilePath(const node& n, std::vector<std::string>& audio_path) {
            switch (n.type) {
                case AudioType::STR_TEXT:
                case AudioType::INT_TEXT: {
                    // 统一处理为字符播报（数字也转成字符串）
                    std::string str;
                    if (n.data.index() == 0)
                        str = std::get<std::string>(n.data);
                    else
                        str = std::to_string(std::get<int>(n.data));

                    for (char c : str) {
                        if (std::isalnum(static_cast<unsigned char>(c))) {
                            audio_path.emplace_back(makePath(c));
                        }
                    }
                    break;
                }

                case AudioType::STR_CN_TEXT:
                case AudioType::INT_CN_TEXT: {
                    int number = 0;
                    if (n.data.index() == 0) {
                        try {
                            number = std::stoi(std::get<std::string>(n.data));
                        } catch (...) {
                            LOG_E(TAG, "Invalid STR_CN_TEXT string\n");
                            break;
                        }
                    } else {
                        number = std::get<int>(n.data);
                    }

                    if (number == 0) {
                        audio_path.emplace_back(makePath("0"));
                        break;
                    }

                    // 分解数字为 万、千、百、十、个
                    int digits[5] = { number / 10000, (number / 1000) % 10, (number / 100) % 10, (number / 10) % 10,
                                      number % 10 };

                    bool hasPrev = false;
                    for (int i = 0; i < 5; ++i) {
                        if (digits[i] != 0) {
                            if (hasPrev && i != 4 && digits[i - 1] == 0)
                                audio_path.emplace_back(makePath("0"));    // 插入“零”
                            audio_path.emplace_back(makePath(std::to_string(digits[i])));
                            switch (i) {
                                case 0:
                                    audio_path.emplace_back(makePath("万"));
                                    break;
                                case 1:
                                    audio_path.emplace_back(makePath("千"));
                                    break;
                                case 2:
                                    audio_path.emplace_back(makePath("百"));
                                    break;
                                case 3:
                                    audio_path.emplace_back(makePath("十"));
                                    break;
                                default:
                                    break;
                            }
                            hasPrev = true;
                        }
                    }
                    break;
                }

                case AudioType::DIRECT: {
                    const std::string& name = std::get<std::string>(n.data);
                    audio_path.emplace_back(makePath(name));
                    break;
                }

                default:
                    LOG_E(TAG, "Unknown AudioType\n");
                    break;
            }
        }
    };
}    // namespace

SysAudio::SysAudio() {
    audio_ = &Audio::getInstance();
    dev_state_ = &DeviceState::getInstance();
}

SysAudio::~SysAudio() {}

void SysAudio::SetSysAudioPath(const std::string& path) {
    sys_audio_path_ = path;
}

void SysAudio::SetConfig(int remindType, std::bitset<32> speechEnable, bool isChinese) {
    remind_type_ = remindType;
    speech_enable_ = speechEnable;
    is_chinese_ = isChinese;
}

// 无效手牌,请检查
void SysAudio::Index0_InvalidCardInfo() {
    if (!speech_enable_[0]) {
        return;
    }

    LOG_I(TAG, "Index0_InvalidCardInfo");

    audio_->AddMusicListNode(
        {
            AudioNode{ AUDIO_TYPE_MP3, dev_state_->audioFilePath + AUDIO_EXPIRED_WRISTBAND },
        },
        AUDIO_PRIORITY_MUSIC, nullptr);
}

// 操作成功。
void SysAudio::Index1_OperationSuccess() {
    if (!speech_enable_[1]) {
        return;
    }

    LOG_I(TAG, "Index1_OperationSuccess");

    audio_->AddMusicListNode(
        {
            AudioNode{ AUDIO_TYPE_MP3, dev_state_->audioFilePath + AUDIO_OPERATION_SUCCESS },
        },
        AUDIO_PRIORITY_MUSIC, nullptr);
}

// ${工号}号，很高兴为您服务${分钟}分钟
void SysAudio::Index2_StartClockSuccess(char* id, int time) {
    if (!speech_enable_[2]) {
        return;
    }

    LOG_I(TAG, "Index2_StartClockSuccess");

    std::vector<node> nodes;
    std::vector<std::string> audio_paths;
    AudioFunc af;

    nodes.emplace_back(node{ is_chinese_ ? AudioType::STR_CN_TEXT : AudioType::STR_TEXT, std::string(id) });
    nodes.emplace_back(node{ AudioType::DIRECT, std::string(AUDIO_HAO) });
    nodes.emplace_back(node{ AudioType::DIRECT, std::string(AUDIO_GLAD_TO_SERVE_YOU) });
    nodes.emplace_back(node{ AudioType::INT_CN_TEXT, time });
    nodes.emplace_back(node{ AudioType::DIRECT, std::string(AUDIO_MINUTE) });

    // 生成每一段路径
    for (const auto& n : nodes) {
        af.GenerateFilePath(n, audio_paths);
    }

    // 转换为 AudioNode 并播放
    std::vector<AudioNode> audio_nodes;
    for (const auto& path : audio_paths) {
        audio_nodes.emplace_back(AudioNode{ AUDIO_TYPE_MP3, path });
    }

    audio_->AddMusicListNode(audio_nodes, AUDIO_PRIORITY_MUSIC, nullptr);
}
